package com.sugon.controller.device;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.DataFilter;
import com.sugon.annotation.LimitSubmit;
import com.sugon.annotation.NonBusinessParamValid;
import com.sugon.entity.*;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.device.consts.DevMaintenanceTicketStatus;
import com.sugon.modules.device.consts.ExceptionSourceType;
import com.sugon.modules.device.model.dto.AmTicketCancelParam;
import com.sugon.modules.device.model.vo.DelayCheckParam;
import com.sugon.modules.device.model.vo.DevAmTicketVO;
import com.sugon.modules.device.model.vo.DevMaintenanceDelayApplyParam;
import com.sugon.modules.device.model.vo.DevMaintenanceTicketDispatchParamVO;
import com.sugon.modules.device.service.IDeviceAmTicketManager;
import com.sugon.modules.sys.consts.SysRole;
import com.sugon.modules.sys.service.INoticeManager;
import com.sugon.service.*;
import com.sugon.utils.PageUtils;
import com.sugon.utils.Query;
import com.sugon.utils.R;
import com.sugon.utils.ShiroUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 设备自主维护工单列表
 *
 * @author YuXD
 * @date 2023-01-23
 */
@Controller
@RequestMapping("devAmTicket")
public class DevAmTicketController {

    @Autowired
    private DevPlanGcService devPlanGcService;
    @Autowired
    private ExcepRecordService excepRecordService;
    @Autowired
    private DevAmTicketService devAmTicketService;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Resource
    private IDeviceAmTicketManager amTicketManager;
    @Resource
    private DevMaintenancePlanChangeService devMaintenancePlanChangeService;
    @Autowired
    private TicketLiveImageService ticketLiveImageService;
    @Autowired
    private INoticeManager noticeManager;
    @Resource
    private SysUserRoleService userRoleService;

    /**
     * 获取当前车间下具有多能工角色的用户列表
     */
    @RequestMapping("/repairUser")
    @ResponseBody
    public R getRepairUser() {
        return R.ok().put("repairUserList", userRoleService.queryDeptUserByRoleId(ShiroUtils.getWorkshop(), SysRole.DNG.getRoleId()));
    }

    /**
     * 查看列表
     */
    @RequestMapping("/list")
    @DataFilter(deptAlias = "DMT.WORKSHOP", userAlias = "DMT.EXECUTOR")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        // 如果查询的执行时间不为空，那么回填年度和周次
        Date executeTime = MapUtil.getDate(params, "executeTime");
        if (executeTime != null) {
            params.put("yearly", DateUtil.year(executeTime));
            params.put("weekOfYear", DateUtil.weekOfYear(executeTime));
        }

         /*
            查看工单结束日期所在的周次查询
         */
        Date executeEndTime = MapUtil.getDate(params, "executeEndTime");
        if (executeEndTime != null) {
            params.put("startTime", DateUtil.formatDateTime(DateUtil.beginOfWeek(executeEndTime)));
            params.put("endTime", DateUtil.formatDateTime(DateUtil.endOfWeek(executeEndTime)));
            params.remove("executeEndTime");
        }


        /*
            PM完成率的维护工单列表也会调用这个接口
            seriesName 和seriesIndex
               seriesName有两种情形：2023-01 和 第1周两种情形
               seriesIndex：0 1 2 3四个值，其中0和2查看已完成的，1和3查看其它情况的
         */
        //  seriesName有两种情形：2023-01 和 第1周两种情形,简单处理
        String seriesName = MapUtil.getStr(params, "seriesName");
        if (StrUtil.isNotEmpty(seriesName)) {
            if (StrUtil.containsAny(seriesName, "第", "周")) {
                // 获取本月的第几周
                Integer weekOfMonth = ReUtil.getFirstNumber(seriesName);
                // 获取本月第weekOfMonth周的第一天
                DateTime dateTime = DateUtil.offsetWeek(DateUtil.beginOfMonth(DateUtil.date()), weekOfMonth - 1);
                params.put("startTime", DateUtil.formatDateTime(DateUtil.beginOfWeek(dateTime)));
                params.put("endTime", DateUtil.formatDateTime(DateUtil.endOfWeek(dateTime)));
            } else if (StrUtil.containsAny(seriesName, "-")) {
                DateTime currentMonth = DateUtil.parseDate(seriesName + "-01");
                params.put("startTime", DateUtil.formatDateTime(DateUtil.beginOfMonth(currentMonth)));
                params.put("endTime", DateUtil.formatDateTime(DateUtil.endOfMonth(currentMonth)));
            }
        }
        // seriesIndex：0 1 2 3四个值，其中0和2查看已完成的，1和3查看其它情况的
        Integer seriesIndex = MapUtil.getInt(params, "seriesIndex");
        if (seriesIndex != null) {
            if (seriesIndex == 0 || seriesIndex == 2) {
                params.put("statusList", CollectionUtil.newArrayList(DevMaintenanceTicketStatus.COMPLETE, DevMaintenanceTicketStatus.DELAY_COMPLETE));
            } else if (seriesIndex == 1 || seriesIndex == 3) {
                params.put("statusList", CollectionUtil.newArrayList(DevMaintenanceTicketStatus.DISPATCHING, DevMaintenanceTicketStatus.WAIT_EXECUTE, DevMaintenanceTicketStatus.MAINTAINING, DevMaintenanceTicketStatus.DELAY_APPLYING, DevMaintenanceTicketStatus.DELAY_MAINTAINING, DevMaintenanceTicketStatus.STOP, DevMaintenanceTicketStatus.OVERTIME, DevMaintenanceTicketStatus.CANCELLING, DevMaintenanceTicketStatus.CANCEL));
            }
        }

        //查询列表数据
        Query query = new Query(params);
        List<DevAmTicketVO> devPlanGcList = devAmTicketService.queryAll(query);
        int total = devAmTicketService.queryAllTotal(query);
        PageUtils pageUtil = new PageUtils(devPlanGcList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    /**
     * 获取设备维护工单现场图片
     */
    @RequestMapping("/{ticketId}/liveImages")
    @ResponseBody
    public R loadLiveImages(@PathVariable("ticketId") String ticketId) {
        return R.ok().put("liveImageList", ticketLiveImageService.getTicketLiveImages(null, ticketId, "MAINTENANCE"));
    }

    /**
     * 自主维护工单取消执行
     *
     * @param cancelParam   取消参数
     * @param bindingResult
     * @return
     */
    @AutoLog(value = "取消AM工单", busModule = BusModule.DEVICE_MAINTENANCE)
    @LimitSubmit(key = "cancelAmTicket:%s")
    @NonBusinessParamValid
    @RequiresPermissions("devAmTicket:cancel")
    @PostMapping("/cancel")
    @ResponseBody
    public R loadLiveImages(@Validated @RequestBody AmTicketCancelParam cancelParam, BindingResult bindingResult) {
        List<String> ticketIdList = cancelParam.getTicketIdList();
        for (String ticketId : ticketIdList) {
            // 校验工单是否存在
            DevAmTicketEntity amTicket = devAmTicketService.queryObject(ticketId);
            if (amTicket == null) {
                return R.error("工单[{}]不存在，请确认！", ticketId);
            }
            amTicket.setStatus(DevMaintenanceTicketStatus.CANCELLING);
            amTicket.setCanceller(ShiroUtils.getUserId());
            amTicket.setCancelTime(DateUtil.date());
            amTicket.setRemark(cancelParam.getRemark());
            devAmTicketService.update(amTicket);
        }
        return R.ok();
    }

    @LimitSubmit(key = "approveAmTicketCancel:%s")
    @AutoLog(value = "审批取消AM工单", busModule = BusModule.DEVICE_MAINTENANCE)
    @RequestMapping("/approve")
    @RequiresPermissions("devAmTicket:approve")
    @ResponseBody
    public R approve(@RequestBody String[] ids) {
        // 自主维护工单必选！
        if (ArrayUtil.isEmpty(ids)) {
            return R.error("自主维护工单必选！");
        }
        // 只可以审批取消申请中的自主维护工单
        for (String id : ids) {
            DevAmTicketEntity devAmTicket = devAmTicketService.queryObject(id);
            if (devAmTicket == null) {
                return R.error("设备自主维护工单不存在，请确认！");
            }
            if (!NumberUtil.equals(DevMaintenanceTicketStatus.CANCELLING, devAmTicket.getStatus())) {
                return R.error("自主维护工单[{}]不是取消申请中的工单，不能进行审批！", devAmTicket.getRepairCode());
            }
            // 修改状态、设置审批人、审批时间
            devAmTicket.setStatus(DevMaintenanceTicketStatus.CANCEL);
            devAmTicket.setApprover(ShiroUtils.getUserId());
            devAmTicket.setApproveTime(DateUtil.date());
            devAmTicketService.update(devAmTicket);
        }
        return R.ok();
    }

    /**
     * 查看信息
     */
    @RequestMapping("/info/{id}")
    @ResponseBody
    public R info(@PathVariable("id") String id) {
        DevPlanGcEntity devPlanGc = devPlanGcService.queryObject(id);

        return R.ok().put("devPlanGc", devPlanGc);
    }

    /**
     * 修改
     */
    @AutoLog("设备自主维护工单--修改")
    @RequestMapping("/update")
    @ResponseBody
    public R update(@RequestBody DevPlanGcEntity devPlanGc) {
        devPlanGcService.update(devPlanGc);

        return R.ok();
    }

    @AutoLog("设备自主维护工单--删除")
    @RequestMapping("/delete")
    @RequiresPermissions("devAmTicket:cancel")
    @ResponseBody
    public R delete(@RequestBody String[] ids) {
        devPlanGcService.deleteBatch(ids);

        return R.ok();
    }


    /**
     * 查看所有列表
     */
    @RequestMapping("/queryAll")
    @ResponseBody
    public R queryAll(@RequestParam Map<String, Object> params) {

        List<DevPlanGcEntity> list = devPlanGcService.queryList(params);

        return R.ok().put("list", list);
    }

    @AutoLog(value = "AM工单派工", busModule = BusModule.DEVICE_MAINTENANCE)
    @NonBusinessParamValid
    @RequestMapping("/dispatchTicket")
    @RequiresPermissions("devAmTicket:addExecuteUser")
    @ResponseBody
    public R addExecuteUser(@Validated @RequestBody DevMaintenanceTicketDispatchParamVO ticketDispatchParam, BindingResult bindingResult) {
        List<String> executor = ticketDispatchParam.getExecutor();
        List<String> ticketIdList = ticketDispatchParam.getTicketIdList();
        DevAmTicketEntity maintenanceTicket = null;

        // 获取不能再次派工的工单状态列表，后续用做比较用
        List<Integer> unDispatchableTicketStatusList = CollectionUtil.newArrayList(DevMaintenanceTicketStatus.DISPATCHING, DevMaintenanceTicketStatus.WAIT_EXECUTE, DevMaintenanceTicketStatus.OVERTIME);

        for (String ticketId : ticketIdList) {
            // 1、校验工单是否存在以及是否完成
            maintenanceTicket = devAmTicketService.queryObject(ticketId);
            if (maintenanceTicket == null) {
                return R.error("设备维护工单不存在，请确认！");
            }
            // 校验是否可派工
            if (!CollectionUtil.contains(unDispatchableTicketStatusList, maintenanceTicket.getStatus())) {
                return R.error("只有 [待分派、待执行、已超期] 状态工单才可以派工！");
            }
            // 重新设置维护人员
            maintenanceTicket.setExecutor(CollectionUtil.join(executor, ","));
            /*
                目前可以派工的有两种：待分派、已超期
                只有待分派的工单需要调整为已派工，已超期的不进行
             */
            if (DevMaintenanceTicketStatus.DISPATCHING.equals(maintenanceTicket.getStatus())) {
                maintenanceTicket.setStatus(DevMaintenanceTicketStatus.WAIT_EXECUTE);
            }
            maintenanceTicket.setDispatchTime(DateUtil.date());
            int updateFlag = devAmTicketService.update(maintenanceTicket);
            if (updateFlag > 0) {
                // 给维护人员发送消息
                noticeManager.pushDeviceAmNotice(maintenanceTicket.getId());
            }
        }
        return R.ok();
    }

    @NonBusinessParamValid
    @AutoLog(value = "AM工单变更申请", busModule = BusModule.DEVICE_MAINTENANCE)
    @RequestMapping("/applyDelay")
    @ResponseBody
    public R applyChange(@Validated @RequestBody DevMaintenanceDelayApplyParam ticketChangeApplyParam, BindingResult bindingResult) {
        // 1、校验工单是否存在以及是否完成
        DevAmTicketEntity ticket = devAmTicketService.queryObject(ticketChangeApplyParam.getTicketId());
        if (ticket == null) {
            return R.error("设备维护工单不存在，请确认！");
        }
        // 延期申请中的不允许申请
        if (DevMaintenanceTicketStatus.DELAY_APPLYING.equals(ticket.getStatus())) {
            return R.error("工单延期申请中，请耐心等待！");
        }
        // 已完成、已关闭、已延期完成的工单不允许延期
        List<Integer> temStatusList = CollectionUtil.newArrayList(DevMaintenanceTicketStatus.COMPLETE, DevMaintenanceTicketStatus.STOP, DevMaintenanceTicketStatus.DELAY_COMPLETE);
        if (temStatusList.contains(ticket.getStatus())) {
            return R.error("工单已完成或已关闭，不允许申请延期！");
        }
        // 只可以延期申请自己负责的工单
        String applier = ShiroUtils.getUserId();
        if (ticket.getExecutor() == null || !StrUtil.contains(ticket.getExecutor(), applier)) {
            return R.error("只可以申请延期自己负责的设备维护工单！");
        }
        // 期望延期时间不得早于工单最晚结束时间
        if (ticketChangeApplyParam.getChangeTime().before(ticket.getFinalEndTime())) {
            return R.error("期望延期时间不得早于工单结束时间！");
        }
        ticketChangeApplyParam.setApplier(applier);
        ticketChangeApplyParam.setDevAmTicket(ticket);
        return amTicketManager.applyChange(ticketChangeApplyParam) ? R.ok() : R.error();
    }

    @NonBusinessParamValid
    @AutoLog(value = "AM工单延期审核", busModule = BusModule.DEVICE_MAINTENANCE)
    @RequestMapping("/delayApply")
    @ResponseBody
    public R delayApply(@Validated @RequestBody DelayCheckParam delayCheckParam, BindingResult bindingResult) {
        // 1、校验工单是否存在以及是否完成
        DevAmTicketEntity ticket = devAmTicketService.queryObject(delayCheckParam.getTicketId());
        if (ticket == null) {
            return R.error("设备维护工单不存在，请确认！");
        }
        // 只有延期申请中的设备维护工单才可以审核
        if (!DevMaintenanceTicketStatus.DELAY_APPLYING.equals(ticket.getStatus())) {
            return R.error("只可以审核处于[延期申请中]的设备维护工单！");
        }
        // 校验该维护工单的延期申请记录是否存在
        DevMaintenancePlanChangeEntity applyRecord = devMaintenancePlanChangeService.queryUnHandledByTicketId(delayCheckParam.getTicketId());
        if (applyRecord == null) {
            return R.error("该工单的延期申请记录不存在，请确认！");
        }
        delayCheckParam.setApplyRecord(applyRecord);
        delayCheckParam.setAmTicket(ticket);
        return amTicketManager.checkChange(delayCheckParam) ? R.ok() : R.error();
    }

    /**
     * @return
     */
    @RequestMapping("/error")
    @AutoLog(value = "AM工单异常添加", busModule = BusModule.DEVICE_MAINTENANCE)
    @ResponseBody
    public R error(@RequestBody ExcepRecordEntity excepRecordEntity) {
        String devId = excepRecordEntity.getDevId();
        if (StrUtil.isEmpty(devId)) {
            return R.error("发生异常设备必填！");
        }
        DeviceInfoEntity deviceInfo = deviceInfoService.queryObject(devId);
        if (deviceInfo != null) {
            excepRecordEntity.setWorkshopId(deviceInfo.getDevFarm());
        }
        excepRecordEntity.setDutyUserId(ShiroUtils.getUserId());
        excepRecordEntity.setCreateUser(ShiroUtils.getUserId());
        excepRecordEntity.setExType(ExceptionSourceType.AM);
        return excepRecordService.save(excepRecordEntity) > 0 ? R.ok() : R.error();
    }

    /**
     * 催办保存
     *
     * @param
     * @return
     */
    @RequestMapping("/urgeSave")
    @ResponseBody
    public R urgeSave(@RequestBody DevReportUrgeEntity devReportUrge) {
        return amTicketManager.urge(devReportUrge.getRepairNo(), ShiroUtils.getUserId()) ? R.ok() : R.error();
    }

}
